UNPKG

15 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <title>JSDoc: Tutorial: Query Examples</title>
6
7 <script src="scripts/prettify/prettify.js"> </script>
8 <script src="scripts/prettify/lang-css.js"> </script>
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14</head>
15
16<body>
17
18<div id="main">
19
20 <h1 class="page-title">Tutorial: Query Examples</h1>
21
22 <section>
23
24<header>
25
26
27 <h2>Query Examples</h2>
28</header>
29
30<article>
31 <h3>Designing Queries</h3><p>LokiJS has evolved several mechanisms for querying the database. It may be difficult at first to determine which method you should use for querying, so this page will attempt to describe features and limitations of the various methods.</p>
32<p>At the highest level of abstraction, let us divide the methods into these categories : </p>
33<ul>
34<li>Core Methods - simple, yet powerful method for queries applied directly to a collection.</li>
35<li>Chaining (via Resultsets) - allows for sorting, limiting, offsets, and multiple queries in sequence.</li>
36<li>Chaining Transforms - similar to method chaining above, yet defined in object structure which can be serialized.</li>
37<li>DynamicViews - allows for optimal performance and availability commonly used queries with potentially large resultsets.</li>
38</ul>
39<p>Within each of those methods, your queries generally fall into 'find' and 'where' categories. </p>
40<h3>'Where' queries</h3><p>These queries leverage javascript functions to filter data. This is the slowest but most versatile method for filtering documents in a collection. Essentially we will test your filter on every document in the collection to see if it should be in the results.</p>
41<pre class="prettyprint source lang-javascript"><code>// simple anonymous filter
42var results = coll.where(function(obj) {
43 return obj.legs === 8;
44});
45
46// -or- set up named filter function
47function sleipnirFilter(obj) {
48 return obj.legs === 8;
49}
50
51// and then pass that
52results = coll.where(sleipnirFunction);</code></pre><h3>'Find' queries</h3><p>Find queries are based on subset of mongo query syntax and are capable of utilizing indexes to speed up queries. When used with Collection Transforms or Dynamic Views, these filters can be saved into the database itself. This is the preferred method for querying a Loki database. Query everything (or filter as much as you can) with find queries, and use 'where' filtering if there are edge cases which find does not support (or does not support yet).</p>
53<h3>'Find' Operators</h3><p>The primary operators currently supported are : </p>
54<ul>
55<li>$eq - filter for document(s) with property of (strict) equality</li>
56<li>$dteq - filter for document(s) with date property equal to provided date value</li>
57<li>$gt - filter for document(s) with property greater than provided value</li>
58<li>$gte - filter for document(s) with property greater or equal to provided value</li>
59<li>$lt - filter for document(s) with property less than provided value</li>
60<li>$lte - filter for document(s) with property less than or equal to provided value</li>
61<li>$between - filter for documents(s) with property between provided vals</li>
62<li>$ne - filter for document(s) with property not equal to provided value</li>
63<li>$regex - filter for document(s) with property matching provided regular expression</li>
64<li>$in - filter for document(s) with property matching any of the provided array values.</li>
65<li>$contains - filter for document(s) with property containing the provided value</li>
66<li>$containsAny - filter for document(s) with property containing any of the provided values</li>
67<li>$containsNone - filter for documents(s) with property containing none of the provided values</li>
68<li>$and - filter for documents which meet all nested subexpressions</li>
69<li>$or - filter for documents which meet any of the nested subexpressions</li>
70</ul>
71<h3>Features which support 'find' queries</h3><p>These operators can be used to compose find filter objects which can be used within : </p>
72<ul>
73<li>Collection find()</li>
74<li>Collection findOne()</li>
75<li>(chained) Resultset find()</li>
76<li>Collection Transforms</li>
77<li>DynamicView applyFind()</li>
78</ul>
79<h3>'Find' Operator Examples :</h3><p>$eq / $ne : </p>
80<pre class="prettyprint source lang-javascript"><code>// explicit
81var results = coll.find({'Name': { '$eq' : 'Odin' }});
82
83// implicit (assumes equality operator)
84results = coll.find({'Name': 'Odin'});
85
86// not equal test
87results = coll.find({'legs': { '$ne' : 8 }});</code></pre><p>$regex:</p>
88<pre class="prettyprint source lang-javascript"><code>// pass in raw regex
89var results = coll.find({'Name': { '$regex' : /din/ }});
90
91// or pass in string pattern only
92results = coll.find({'Name': { '$regex': 'din' }});
93
94// or pass in [pattern, options] string array
95results = coll.find({'Name': { '$regex': ['din', 'i'] }});</code></pre><blockquote>
96<p><em>If using regex operator within a named transform or dynamic view filter, it is best to use the latter two examples since raw regex does not seem to serialize/deserialize well.</em></p>
97</blockquote>
98<p>$in:</p>
99<pre class="prettyprint source lang-javascript"><code>var users = db.addCollection(&quot;users&quot;);
100users.insert({ name : 'odin' });
101users.insert({ name : 'thor' });
102users.insert({ name : 'svafrlami' });
103
104// match users with name in array set ['odin' or 'thor']
105var results = users.find({ 'name' : { '$in' : ['odin', 'thor'] } });</code></pre><p>$between</p>
106<pre class="prettyprint source lang-javascript"><code>// match users with count value between 50 and 75
107var results = users.find({ count : { '$between': [50, 75] });</code></pre><p>$contains / $containsAny / $containsNone</p>
108<pre class="prettyprint source lang-javascript"><code>var users = db.addCollection(&quot;users&quot;);
109users.insert({ name : 'odin', weapons : ['gungnir', 'draupnir']});
110users.insert({ name : 'thor', weapons : ['mjolnir']});
111users.insert({ name : 'svafrlami', weapons : ['tyrfing']});
112users.insert({ name : 'arngrim', weapons : ['tyrfing']});
113
114// returns 'svafrlami' and 'arngrim' documents
115var results = users.find({ 'weapons' : { '$contains' : 'tyrfing' } });
116
117// returns 'svafrlami', 'arngrim', and 'thor' documents
118results = users.find({ 'weapons' : { '$containsAny' : ['tyrfing', 'mjolnir'] } });
119
120// returns 'svafrlami' and 'arngrim'
121results = users.find({ 'weapons' : { '$containsNone' : ['gungnir', 'mjolnir'] } });</code></pre><h3>Composing Nested Queries</h3><p>$and : </p>
122<pre class="prettyprint source lang-javascript"><code>// fetch documents matching both sub-expressions
123var results = coll.find({
124 '$and': [{
125 'Age' : {
126 '$gt': 30
127 }
128 },{
129 'Name' : 'Thor'
130 }]
131});</code></pre><p>$or : </p>
132<pre class="prettyprint source lang-javascript"><code>// fetch documents matching any of the sub-expressions
133var results = coll.find({
134 '$or': [{
135 'Age' : {
136 '$gte': '40'
137 }
138 },{
139 'Name' : 'Thor'
140 }]
141});</code></pre><h3>Programmatic query examples</h3><p>The following queries return the same results : </p>
142<pre class="prettyprint source lang-javascript"><code>// Core collection 'find' method
143var results = coll.find({'Age': {'$gte': 40}});
144
145// Resultset chaining
146results = coll.chain().find({'Age': {'$gte': 40}}).data();
147
148// Core collection 'where' method
149results = coll.where(function(obj) {
150 return obj.Age >= 40;
151});</code></pre><h3>Resultset chaining</h3><p>The core 'find' and 'where' functionality are two of the main building blocks that Resultset chaining allows you to build from. Other methods available include : </p>
152<ul>
153<li>limit - allows limiting the results to a specific document count.</li>
154<li>offset - allows skipping the first number of documents from the results.</li>
155<li>branch - useful for splitting a query path into multiple branches.</li>
156<li>simplesort - just pass a property name and your resulset will be sorted by this.</li>
157<li>sort - allows you to provide your own comparison function to sort the resultset with.</li>
158<li>compoundsort - allows you sort based on multiple properties in ascending or descending order.</li>
159<li>update - used to run an update operation (javascript function) on all documents currently in the resultset.</li>
160<li>remove - removes all document objects which are currently in resultset from collection (as well as resultset)</li>
161<li>map - maps into a new anonymous collection, provide this with a map function</li>
162<li>mapReduce - allows you to specify both a map function and a reduce function on the current resultset data.</li>
163<li>eqJoin - Left joining two sets of data. Join keys can be defined or calculated properties</li>
164<li>transform - at the resultset level, this requires a raw transform array. When beginning a chain, a named or raw transform may be passed in to the chain method. See 'Collection Transforms' wiki page for more details.</li>
165</ul>
166<p>An example making better use of chaining might be the following : </p>
167<pre class="prettyprint source lang-javascript"><code>var results = coll.chain()
168 .find({'Age': {'$gt':20}})
169 .where(function(obj) {
170 return obj.Country.indexOf('FR') === 0;
171 })
172 .simplesort('Name')
173 .offset(100)
174 .limit(25)
175 .data();</code></pre><h3>Resultset branching</h3><p>Resultsets and their results are not meant to be 'held' around. Those situations usually involve utilitizing Dynamic Views to keep results up-to-date. You can however temporarily branch a resulset as often as you like, provided that you use the results right away (before any inserts/updates/deletes can occur). Dynamic views also allows branching results which, in turn, takes its internal resultset and uses this branch to allow you to further query and transform its results without the initial penalty of the already executed filters.</p>
176<p>A simple example of collection branching might appear as follows : </p>
177<pre class="prettyprint source lang-javascript"><code>var baseResulset = coll.chain().find({'Age': {'$gte': 40}});
178var branchedResulset = baseResultset.branch();
179
180var usResults = baseResultset.find({'Country': 'US'}).data();
181var ieResults = branchedResulset.find({'Country': 'IE'}).data();</code></pre><p>The advantage being if the base resulset query was time consuming, your subsequent branches would not need to incur that common cost. Branching is typically more useful in large collections or extremely time sensitive applications. </p>
182<p>Retaining the resultset (even when not branching) can be done to break up a chain into several parts if you need to examine data() or document counts at various stages in the chain.</p>
183<h3>Strategies for determining which methods to use</h3><p>Wherever possible, use 'Find' queries over 'Where' queries. 'Find' queries are able to utilize indexes if they are applied and are relevant to your query.</p>
184<p>The 'Core' (Collection) querying methods (Collection.where(), Collection.find(), Collection.findOne(), Collection.by()) are the best method for learning lokijs. For many applications this may be sufficient for your query needs. Features not (yet?) available would be sorting, limiting, offsets and other higher level transformations. </p>
185<p>Chaining queries is done via a call to collection.chain() which instances the Resultset class. In doing so, we establish a 'state' for our queries. You can string together multiple 'find', 'where', sorts, limit, offset (etc) operations to progressively filter and transform your results. You may also establish query branching to split off your query into multiple directions as efficiently as possible. Chaining via resultsets is still intended for instant evaluation. If you keep a resultset around in memory, it is not guaranteed to remain up-to-date if the underlying data changes. Only the first chained operation may use database filters, so prioritize your most expensive find() filter (which has an index applied) to be the first chained operation.</p>
186<p>Chaining via transforms allows the same functionality as method chaining to be defined in an object, functioning similar to a stored procedure. Since it is an object representation, it can (optionally) be named and saved along with your database. This method is also intended for instant evaluation.</p>
187<p>DynamicViews are intended to keep a 'fresh' database view readily available. You may apply 'find' and 'where' filters, and specify sorting. As documents are inserted, updated, or removed, you view will immediately be kept up-to-date. This ensures optimal read performance against your view, as it is always up-to-date. If your view requires further filtering, you may branch resultsets off of it. The moment at which you branch off a DynamicView, you take a snapshot of the DynamicView's internal resultset at that point in time, allowing you to perform a wide variety of chaining operations for immediate evaluation. So if you do DynamicView branching, consider the view as guaranteed freshness and the branches as quick disposable branches to be evaluated.</p>
188</article>
189
190</section>
191
192</div>
193
194<nav>
195 <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Collection.html">Collection</a></li><li><a href="DynamicView.html">DynamicView</a></li><li><a href="Loki.html">Loki</a></li><li><a href="LokiEventEmitter.html">LokiEventEmitter</a></li><li><a href="LokiFsAdapter.html">LokiFsAdapter</a></li><li><a href="LokiFsStructuredAdapter.html">LokiFsStructuredAdapter</a></li><li><a href="LokiIndexedAdapter.html">LokiIndexedAdapter</a></li><li><a href="LokiLocalStorageAdapter.html">LokiLocalStorageAdapter</a></li><li><a href="LokiMemoryAdapter.html">LokiMemoryAdapter</a></li><li><a href="LokiPartitioningAdapter.html">LokiPartitioningAdapter</a></li><li><a href="Resultset.html">Resultset</a></li></ul><h3>Tutorials</h3><ul><li><a href="tutorial-Autoupdating Collections.html">Autoupdating Collections</a></li><li><a href="tutorial-Changes API.html">Changes API</a></li><li><a href="tutorial-Collection Transforms.html">Collection Transforms</a></li><li><a href="tutorial-Indexing and Query performance.html">Indexing and Query performance</a></li><li><a href="tutorial-Loki Angular.html">Loki Angular</a></li><li><a href="tutorial-Persistence Adapters.html">Persistence Adapters</a></li><li><a href="tutorial-Query Examples.html">Query Examples</a></li></ul>
196</nav>
197
198<br class="clear">
199
200<footer>
201 Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun Dec 18 2016 19:39:52 GMT-0500 (Eastern Standard Time)
202</footer>
203
204<script> prettyPrint(); </script>
205<script src="scripts/linenumber.js"> </script>
206</body>
207</html>
\No newline at end of file